Rust から C の関数を呼び出す
from 項目34:FFI境界を通過するものを制御しよう
最も簡単な FFI 操作は、ポインタ や 参照、メモリアドレス が関係しない「値」を引数とする C の関数を呼び出すこと
code:lib.c
#include "lib.h"
int add(int x, int y) {
return x + y;
}
code:lib.h
#ifndef LIB_H
#define LIB_H
int add(int x, int y);
#endif
上記の add 関数を呼び出すには、以下のように記述する
code:rs
use std::os::raw::c_int;
extern "C" {
pub fn add(x: c_int, y: c_int) -> c_int;
}
extern "C" は関数の定義を外部 C 言語のライブラリが提供することを示す
これを付けた関数は自動的に no_mangle (マングリング が無効)となる
warning.icon
Rust の FFI コードは自動的に unsafe になる ため、unsafe { } で囲む必要がある
(項目16:unsafeコードを書かないようにしよう のアドバイスは適用できない)
「FFI 境界 ではサイズ指定の型を使おう」
∵ 上記のコードでは、C 言語で使われている int 型が std::os::raw::c_int と対応しているが、等しくない可能性があるため
したがって、C 言語では <stdint.h> で定義されている型(e.g. uint32_t)を使おう
int や long、size を使っているコードの場合は諦める
C とRust の宣言が一致しなくても、ビルドツールは警告を出さないため実行するまで分からない
∵ 自動的に マングリング が無効になることで、名前の一致しか見ない(関数シグネチャなどは見ない)ためマングリング
回避策: 項目35:手動でFFIマッピングを書かずにbindgenを用いよう
#Rust #Effective_Rust_―_Rustコードを改善し、エコシステムを最大限に活用するための35項目